//
//  Date+Ext.swift
//  TTCOM
//
//  Created by Toj on 6/2/22.
//

import Foundation

/// 时间戳换算
public enum DTTimestampType {
    /// 秒
    case s
    /// 毫秒
    case ms
    /// 微秒
    case us
}

/// DT = Date
public extension Date {
    
    func to_timestamp(type: DTTimestampType = .s) -> TimeInterval {
        switch type {
        case .s:
            return to_timestamp_s
        case .ms:
            return to_timestamp_ms
        case .us:
            return to_timestamp_us
        }
    }
    
    var to_timestamp: TimeInterval {
        return timeIntervalSince1970
    }
    
    var to_timestamp_s: TimeInterval {
        return timeIntervalSince1970
    }
    
    var to_timestamp_ms: TimeInterval {
        let timestamp = timeIntervalSince1970 * 1000
        return timestamp
    }
    
    var to_timestamp_us: TimeInterval {
        let timestamp = timeIntervalSince1970 * 1000 * 1000
        return timestamp
    }
}

// MARK: - 年
public extension Date {
    
    /** 是否是今年 */
    func dt_isThisYear(equally date: Date) -> Bool {
        // 日历
        let calendar = Calendar.current
        
        let nowYear = calendar.component(.year, from: date)
        let selfYear = calendar.component(.year, from: self)
        
        return nowYear == selfYear
    }
    
    /** 是否是今年 */
    var dt_isThisYear: Bool {
        return dt_isThisYear(equally: Date())
    }
}

// MARK: - 月
public extension Date {
    
    // 当前时间月头1天
    var dt_firstDay: Date {
        let component: Set<Calendar.Component> = [.year,
                                                  .month,
                                                  .day,
                                                  .hour,
                                                  .minute,
                                                  .second,
                                                  .nanosecond]
        var cpts = Calendar.current.dateComponents(component, from: self)
        cpts.day = 1 // 天
        cpts.hour = 0 // 时
        cpts.minute = 0 // 分
        cpts.second = 0 // 秒
        cpts.nanosecond = 0 // 纳秒
        let _date = Calendar.current.date(from: cpts) ?? Date()
        return _date
    }
    
    var dt_lastDay: Date {
        // 下个月的第一天
        let nextMonth = dt_firstDayByAdd(month: 1)
        // -1 = 这个月的最后1天
        let lastDay = nextMonth.addingTimeInterval(-1)
        return lastDay
    }
    
    // 下个月头1天
    var dt_firstDayOfNextMonth: Date {
        let component: Set<Calendar.Component> = [.year,
                                                  .month,
                                                  .day,
                                                  .hour,
                                                  .minute,
                                                  .second,
                                                  .nanosecond]
        var cpts = Calendar.current.dateComponents(component, from: self)
        cpts.year = 0
        cpts.month = 1
        cpts.day = 0
        cpts.day = 0 // 天
        cpts.hour = 0 // 时
        cpts.minute = 0 // 分
        cpts.second = 0 // 秒
        cpts.nanosecond = 0 // 纳秒
        let _date = Calendar.current.date(byAdding: cpts, to: dt_firstDay) ?? Date()
        return _date
    }
    
    // 上个月头1天
    var dt_firstDayOfPreviousMonth: Date {
        let component: Set<Calendar.Component> = [.year,
                                                  .month,
                                                  .day,
                                                  .hour,
                                                  .minute,
                                                  .second,
                                                  .nanosecond]
        var cpts = Calendar.current.dateComponents(component, from: self)
        cpts.year = 0
        cpts.month = -1
        cpts.day = 0
        cpts.day = 0 // 天
        cpts.hour = 0 // 时
        cpts.minute = 0 // 分
        cpts.second = 0 // 秒
        cpts.nanosecond = 0 // 纳秒
        let _date = Calendar.current.date(byAdding: cpts, to: dt_firstDay) ?? Date()
        return _date
    }
    
    func dt_firstDayByAdd(month: Int) -> Date {
        var cpts = DateComponents()
        cpts.year = 0
        cpts.month = month
        cpts.day = 0
        cpts.hour = 0
        cpts.minute = 0
        cpts.second = 0
        cpts.nanosecond = 0
        let _date = Calendar.current.date(byAdding: cpts, to: dt_firstDay) ?? Date()
        return _date
    }
}

// MARK: - 日
public extension Date {
    
    // 同一天
    // 86400秒 = 24 * 60 * 60
    func dt_isSameDay(_ date: Date) -> Bool {
        let startDay = Int(date.timeIntervalSince1970) / 86400
        let endDay = Int(self.timeIntervalSince1970) / 86400
        return startDay == endDay
    }
    
    /** 是否是明天 */
    func dt_isTomorrow(equally date: Date) -> Bool {
        // 日期格式化类
        let fmt = DateFormatter()
        fmt.dateFormat = "yyyy-MM-dd"
        
        guard let nowDate = fmt.date(from: fmt.string(from: date)),
              let selfDate = fmt.date(from: fmt.string(from: self))
        else { return false }
        
        // 日历
        let calendar = Calendar.current
        let components: Set<Calendar.Component> = [.year, .month, .day]
        let cmps = calendar.dateComponents(components, from: selfDate, to: nowDate)
        
        let isYesterday = cmps.year == 0 && cmps.month == 0 && cmps.day == -1
        return isYesterday
    }
    
    /** 是否是明天 */
    var dt_isTomorrow: Bool {
        return dt_isTomorrow(equally: Date())
    }
     
    /** 是否是今天 */
    func dt_isToday(equally date: Date) -> Bool {
        // 日历
        let calendar = Calendar.current
        let components: Set<Calendar.Component> = [.year, .month, .day]
        
        let nowCmps = calendar.dateComponents(components, from: date)
        let selfCmps = calendar.dateComponents(components, from: self)
        
        let isToday =
        nowCmps.year == selfCmps.year &&
        nowCmps.month == selfCmps.month &&
        nowCmps.day == selfCmps.day
        return isToday
    }
    
    /** 是否是今天第二种实现 */
    var dt_isToday: Bool {
        return dt_isToday(equally: Date())
    }
    
    /** 是否是昨天 */
    // 2014-12-31 23:59:59 -> 2014-12-31
    // 2015-01-01 00:00:01 -> 2015-01-01
    func dt_isYesterday(equally date: Date) -> Bool {
        // 日历
        let calendar = Calendar.current
        let components: Set<Calendar.Component> = [.year, .month, .day]
        let cmps = calendar.dateComponents(components, from: self, to: date)
        let isYesterday = cmps.year == 0 && cmps.month == 0 && cmps.day == 1
        return isYesterday
    }
    
    /** 是否是昨天 */
    var dt_isYesterday: Bool {
        return dt_isYesterday(equally: Date())
    }
    
    /** 是否是1天内 */
    func dt_isInOneDay(equally date: Date) -> Bool {
        // 日历
        let calendar = Calendar.current
        let components: Set<Calendar.Component> = [.year, .month, .day]
        let cmps = calendar.dateComponents(components, from: self, to: date)
        
        let isInOneDay = cmps.year == 0 && cmps.month == 0 && cmps.day == 0
        return isInOneDay
    }
    
    /** 是否是1天内 */
    var dt_isInOneDay: Bool {
        return dt_isInOneDay(equally: Date())
    }
}

// MARK: - 时间格式化
public extension Date {
    
    /**
     时间 梯度格式化
     - 区间(今年, ~): yyyy-MM-dd(x年x月x日)
     - 区间[非今日, 今年]:
     - 1. 区间[昨天]: "昨天 HH:mm"
     - 2. 区间[非昨天, 今年]: "MM-dd"
     - 区间[~, 今日]:
     - 1. 区间[1时, 今日]: "n小时前"
     - 2. 区间[1分, 1时): "n分钟前"
     - 3. 区间[0秒, 1分): "刚刚"
     */
    func to_dateSeries(equally date: Date) -> String {
        var dateString = "刚刚"
        let formatter = DateFormatter()
        
        guard dt_isThisYear(equally: date) else {
            // 非今年
            formatter.dateFormat = "yyyy-MM-dd"
            dateString = formatter.string(from: self)
            return dateString
        }
    
        // 今年
        guard dt_isToday(equally: date) else {
            // 非今天
           guard !dt_isYesterday(equally: date) else {
               // 昨天
               formatter.dateFormat = "昨天 HH:mm"
               dateString = formatter.string(from: self)
               return dateString
            }
            
            // 非昨天, 今年的其他天(除开今天、昨天)
            formatter.dateFormat = "MM-dd"
            dateString = formatter.string(from: self)
            return dateString
        }
        
        // 今天
        let calendar = NSCalendar.current
        let components: Set<Calendar.Component> = [.hour, .minute, .second]
        let cmps = calendar.dateComponents(components, from: self, to: date)
        
        let hour = cmps.hour ?? 0
        guard hour < 1 else {
            // 时间间隔 >= 1小时
            dateString = String(format: "%zd小时前", hour)
            return dateString
        }
        
        let minute = cmps.minute ?? 0
        guard minute >= 1 else {
            return dateString
        }
        // 1小时 > 时间间隔 >= 1分钟
        dateString = String(format: "%zd分钟前", minute)
        return dateString
    }
    
    /**
     时间梯度, 发布时间显示规则
     - 区间[0, 30分钟): 刚刚
     - 区间[30分钟, 1天): HH:mm(24小时制)
     - 区间[1天, 今年]: MM-dd(x月x日)
     - 区间(今年, ~): yyyy-MM-dd(x年x月x日)
     */
    func st_dateSeries(equally date: Date) -> String {
        var dateString = "刚刚"
        let formatter = DateFormatter()
        guard dt_isThisYear(equally: date) else {
            // 非今年
            formatter.dateFormat = "yyyy-MM-dd"
            dateString = formatter.string(from: self)
            return dateString
        }
    
        // 今年
        guard dt_isInOneDay(equally: date) else {
            // 1天内
            formatter.dateFormat = "MM-dd"
            dateString = formatter.string(from: self)
            return dateString
        }
        
        // 1天内
        let calendar = NSCalendar.current
        let components: Set<Calendar.Component> = [.hour, .minute, .second]
        let cmps = calendar.dateComponents(components, from: self, to: date)
        
        let hour = cmps.hour ?? 0
        let minute = cmps.minute ?? 0
        if hour == 0, minute < 30 { return dateString }
        
        // 时间间隔 >= 30分钟
        formatter.dateFormat = "HH:mm"
        dateString = formatter.string(from: self)
        return dateString
    }
}
